package com.uinnova.product.eam.service.impl;

import com.binary.jdbc.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.base.diagram.comm.model.ESDiagramNode;
import com.uinnova.project.db.eam.ESDiagramNodeDao;
import com.uino.bean.cmdb.base.ESCIInfo;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

public class CiTask implements Runnable{

    private ConcurrentLinkedQueue<List<String>> allCiCodeQueue;
    private List<ESCIInfo> returnVals;
    private List<ESDiagram> diagramList;
    private ESDiagramNodeDao esDiagramNodeDao;

    private CountDownLatch countDownLatch;

    public CiTask(ConcurrentLinkedQueue<List<String>> allCiCodeQueue, List<ESCIInfo> returnVals, List<ESDiagram> diagramList, ESDiagramNodeDao esDiagramNodeDao, CountDownLatch countDownLatch) {
        this.allCiCodeQueue = allCiCodeQueue;
        this.returnVals = returnVals;
        this.diagramList = diagramList;
        this.esDiagramNodeDao = esDiagramNodeDao;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        Set<Long> diagramIdSet = diagramList.stream().map(ESDiagram::getId).collect(Collectors.toSet());
        BoolQueryBuilder boolQueryLinkBuilder = QueryBuilders.boolQuery();
        boolQueryLinkBuilder.must(QueryBuilders.termsQuery("diagramId",diagramIdSet));
        long count = esDiagramNodeDao.countByCondition(boolQueryLinkBuilder);
        List<ESDiagramNode> esDiagramNodes = new ArrayList<>();
        try {
            if (count > 0) {
                Map<String, Page<ESDiagramNode>> nodeMap = esDiagramNodeDao.getScrollByQuery(1, 3000, boolQueryLinkBuilder, "id", true);
                String scrollId = nodeMap.keySet().iterator().next();
                if (nodeMap.get(scrollId).getData() != null && nodeMap.get(scrollId).getData().size() > 0) {
                    List<ESDiagramNode> firstData = nodeMap.get(scrollId).getData();
                    esDiagramNodes.addAll(firstData);
                }
                if (nodeMap.get(scrollId).getTotalRows() > 3000) {
                    while (true) {
                        List<ESDiagramNode> rltNextResult = esDiagramNodeDao.getListByScroll(scrollId);
                        if (rltNextResult != null && rltNextResult.size() > 0) {
                            esDiagramNodes.addAll(rltNextResult);
                        } else {
                            break;
                        }
                    }
                }
                List<String> ciCodes = esDiagramNodes.stream().map(ESDiagramNode::getCiCode)
                        .filter(item -> StringUtils.isNotEmpty(item))
                        .distinct().collect(Collectors.toList());
                for (ESDiagramNode esDiagramNode : esDiagramNodes) {
                    String nodeJson = esDiagramNode.getNodeJson();
                    ObjectMapper objectMapper = new ObjectMapper();
                    JsonNode rootNode = objectMapper.readTree(nodeJson);
                    JsonNode itemsNode = rootNode.get("items");
                    if (itemsNode != null && itemsNode.isArray()) {
                        for (JsonNode itemNode : itemsNode) {
                            JsonNode ciCodeNode = itemNode.get("ciCode");
                            if (ciCodeNode != null) {
                                String ciCode = ciCodeNode.asText();
                                ciCodes.add(ciCode);
                            }
                        }
                    }
                }
                List<String> findCode = returnVals.stream().filter(item -> ciCodes.contains(item.getCiCode())).map(item -> item.getCiCode()).distinct().collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(findCode)) {
                    allCiCodeQueue.add(findCode);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            countDownLatch.countDown();
        }
    }
}
